import math
import os
from quopri import encodestring
import shutil
import sys
import zipfile

import rarfile
import py7zr
import io


wc_num = 3  # 判断两文件夹是否相等的大小误差值

tpgs = ['.jpg', '.jpeg', '.png', '.JPG', '.JPEG', '.PNG', '.bmp', '.BMP', '.gif', '.GIF', '.webp', '.WEBP']

if not os.path.exists("UnRAR.exe"):
    print("无法找到UnRAR")
    input("按任意键结束")
    sys.exit()
else:
    print("已找到UnRAR")

def un_ziprar(file_name, code=0, flag='123'):  # 解压
    zip_size = 0  # 压缩包内部文件总大小
    zip_size2 = 0  # 解压后文件大小
    pd1 = 0  # 判断压缩包内有无jpg，png图片
    file_name_dir = os.path.splitext(file_name)[0]  # 获取不含后缀的文件地址作为文件夹名
    if code == 1:
        file_name_dir = os.path.splitext(file_name)[0]
    elif code == 0:
        file_name_dir = os.path.splitext(file_name)[0] + '_f'
    else:
        print("code错误")
    # 判断code并进行操作
    is_zipfile_flag = zipfile.is_zipfile(file_name)
    file_flag = 0  # 判断是rar还是zip压缩
    if not is_zipfile_flag:
        file_flag = 1
        is_rarfile_flag = rarfile.is_rarfile(file_name)
        if not is_rarfile_flag:
            file_flag = 2
            is_7zfile_flag = py7zr.is_7zfile(file_name)
            if not is_7zfile_flag:
                print(file_name + "不是支持的压缩文件")
                return 1
    if file_flag == 0:
        with zipfile.ZipFile(file_name) as zip_file:
            for names in zip_file.namelist():
                zip_size += zip_file.getinfo(names).file_size  # 获取压缩包内部文件大小
                if pd1 == 0 and os.path.splitext(names)[1] in tpgs:
                    pd1 = 1
                if names == flag:  # 根据标志判断压缩包内部图片是否已经压缩过
                    print(file_name + "压缩包内文件已压缩")
                    zip_file.close()
                    return 1
            if pd1 == 0:
                print(file_name + "内部无可处理图片")
                return 1
            if os.path.isdir(file_name_dir):
                # 如果文件夹存在判断大小是否等于压缩包，防止重复
                zip_size2 = getdirsize(file_name_dir + "/")
                if math.fabs(zip_size - zip_size2) / 1024 < wc_num and zip_size > 0 and zip_size2 > 0:
                    print(file_name + "文件应该已解压")
                    zip_file.close()
                    return 1
                else:
                    for _, _, filenames in os.walk(file_name_dir + "/"):
                        for filename in filenames:
                            if filename == flag:
                                print(file_name + "文件已解压并且图片已压缩")
                                zip_file.close()
                                return 1
            else:
                os.mkdir(file_name_dir)
            print(file_name + "开始解压")
            try:
                zip_file.extractall(winapi_path(file_name_dir))  # 解压
            except:
                shutil.rmtree(file_name_dir)
                print(file_name + "解压失败")
                return 1

        zip_size2 = getdirsize(file_name_dir + "/")  # 获取解压后文件夹大小
        if math.fabs(zip_size - zip_size2) / 1024 < wc_num and zip_size > 0 and zip_size2 > 0:
            print(file_name + "解压成功")
            if code == 1:
                os.remove(file_name)
                print(file_name + "删除成功")
            return 0
        else:
            print(file_name + "解压有猫饼")
            return 1
        # 解压zip 解决zipfile乱码问题https://www.cnblogs.com/rskdst/p/11907745.html
    elif file_flag == 1:
        with rarfile.RarFile(file_name) as rar_file:
            for names in rar_file.namelist():
                zip_size += rar_file.getinfo(names).file_size  # 获取压缩包内部文件大小
                if pd1 == 0 and os.path.splitext(names)[1] in tpgs:
                    pd1 = 1
                if names == flag:  # 根据标志判断压缩包内部图片是否已经压缩过
                    print(file_name + "压缩包内文件已压缩")
                    return 1
            if pd1 == 0:
                print(file_name + "内部无可处理图片")
                return 1
            if os.path.isdir(file_name_dir):
                # 如果文件夹存在判断大小是否等于压缩包，防止重复
                zip_size2 = getdirsize(file_name_dir + "/")
                if math.fabs(zip_size - zip_size2) / 1024 < wc_num and zip_size > 0 and zip_size2 > 0:
                    print(file_name + "应该已解压")
                    rar_file.close()
                    return 1
                else:
                    for _, _, filenames in os.walk(file_name_dir + "/"):
                        for filename in filenames:
                            if filename == flag:
                                print(file_name + "文件已解压并且图片已压缩")
                                rar_file.close()
                                return 1
            else:
                os.mkdir(file_name_dir)
            print(file_name + "开始解压")
            rar_file.extractall(winapi_path(file_name_dir))
        zip_size2 = getdirsize(file_name_dir + "/")  # 获取解压后文件夹大小
        if math.fabs(zip_size - zip_size2) / 1024 < wc_num and zip_size > 0 and zip_size2 > 0:
            print(file_name + "解压成功")
            if code == 1:
                os.remove(file_name)
                print(file_name + "删除成功")
            return 0
        else:
            print(file_name + "解压有猫饼")
            return 1
    elif file_flag == 2:
        #rar_file = rarfile.RarFile(file_name)
        with py7zr.SevenZipFile(file_name, 'r') as archive:
            for names in archive.getnames():
                # zip_size += py7zr.getinfo(names).file_size  # 获取压缩包内部文件大小
                if pd1 == 0 and os.path.splitext(names)[1] in tpgs:
                    pd1 = 1
                if names == flag:
                    print(file_name + "压缩包内文件已压缩")
                    return 1
            if pd1 == 0:
                print(file_name + "内部无可处理图片")
                return 1
            if os.path.isdir(file_name_dir):
                # 如果文件夹存在判断大小是否等于压缩包，防止重复
                zip_size2 = getdirsize(file_name_dir + "/")
                if math.fabs(zip_size - zip_size2) / 1024 < wc_num and zip_size > 0 and zip_size2 > 0:
                    print(file_name + "应该已解压")
                    return 1
                else:
                    for _, _, filenames in os.walk(file_name_dir + "/"):
                        for filename in filenames:
                            if filename == flag:
                                print(file_name + "文件已解压并且图片已压缩")
                                return 1
            else:
                os.mkdir(file_name_dir)
            print(file_name + "开始解压")
            archive.extractall(file_name_dir)
        zip_size2 = getdirsize(file_name_dir + "/")  # 获取解压后文件夹大小
        if file_flag != 3 and math.fabs(zip_size - zip_size2) / 1024 < wc_num and zip_size > 0 and zip_size2 > 0:
            print(file_name + "解压成功")
            if code == 1:
                os.remove(file_name)
                print(file_name + "删除成功")
            return 0
        elif file_flag == 2:
            print(file_name + "解压成功")
            if code == 1:
                os.remove(file_name)
                print(file_name + "删除成功")
            return 0
        else:
            print(file_name + "解压有猫饼")
            return 1

# code=0 不删除原始压缩包，新压缩包重命名
# code=1 删除原始压缩包，新压缩包不重命名


def pd_ziprar(file_name, flag='123'):
    pd1 = 0  # 判断压缩包内有无jpg，png图片
    is_zipfile_flag = zipfile.is_zipfile(file_name)
    file_flag = 0  # 判断是rar还是zip压缩
   
    if not is_zipfile_flag:
        file_flag = 1
        is_rarfile_flag = rarfile.is_rarfile(file_name)
        if not is_rarfile_flag:
            file_flag = 2
            is_7zfile_flag = py7zr.is_7zfile(file_name)
            if not is_7zfile_flag:
                print(file_name + "不是支持的压缩文件")
                return 1
    if file_flag == 0:
        zip_file = zipfile.ZipFile(file_name)
        for names in zip_file.namelist():
            if pd1 == 0 and os.path.splitext(names)[1] in tpgs:
                pd1 = 1
            if names == flag:  # 根据标志判断压缩包内部图片是否已经压缩过
                print(file_name + "压缩包内文件已压缩")
                zip_file.close()
                return 1
        if pd1 == 0:
            print(file_name + "内部无可处理图片")
            zip_file.close()
            return 1
    elif file_flag == 1:
        rar_file = rarfile.RarFile(file_name)
        for names in rar_file.namelist():
            if pd1 == 0 and os.path.splitext(names)[1] in tpgs:
                pd1 = 1
            if names == flag:  # 根据标志判断压缩包内部图片是否已经压缩过
                print(file_name + "压缩包内文件已压缩")
                rar_file.close()
                return 1
        if pd1 == 0:
            print(file_name + "内部无可处理图片")
            rar_file.close()
            return 1
    elif file_flag == 2:
        with py7zr.SevenZipFile(file_name, 'r') as archive:
            for names in archive.getnames():
                # zip_size += py7zr.getinfo(names).file_size  # 获取压缩包内部文件大小
                if pd1 == 0 and os.path.splitext(names)[1] in tpgs:
                    pd1 = 1
                if names == flag:
                    print(file_name + "压缩包内文件已压缩")
                    return 1
            if pd1 == 0:
                print(file_name + "内部无可处理图片")
                return 1
    return 0


def zip_file(src_dir, code=0, flag='123'):  # 打包压缩
    src_dir=winapi_path(src_dir)
    zip_size = 0
    zip_size2 = 0
    pd1 = 0  # 判断文件夹内部图片是否压缩过，1为压缩过，0为未压缩
    if not os.path.exists(src_dir):
        print(src_dir + "文件夹不存在")
        return 1
    # 判断文件夹是否存在
    if not os.listdir(src_dir):
        print(src_dir + "文件夹为空")
        return 1
    # 判断文件夹是否为空
    zip_name = src_dir + '.zip'
    if os.path.exists(zip_name):
        print(zip_name + " 压缩文件已存在")
        return 1
    # 判断压缩包是否存在
    for folderName, subfolders, filenames in os.walk(src_dir):
        for filename in filenames:
            if filename == flag:
                pd1 = 1
                break
            elif os.path.splitext(filename)[1] is not None and os.path.splitext(filename)[1] in 'rar,zip,RAR,ZIP' and os.path.splitext(filename)[1]!='':
                pd1 = 2
                break
    if pd1 == 0:
        print(src_dir + " 内部图片未被压缩")
        return 1
    # 判断是否进行了图片压缩，没有的话不打成压缩包
    if pd1 == 2:
        print(src_dir + " 内部有压缩包存在")
        return 1
    # 判断内部有没有压缩包，避免二次压缩
    z = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_STORED)
    for dirpath, dirnames, filenames in os.walk(winapi_path(src_dir)):
        fpath = dirpath.replace(src_dir, '')
        fpath = fpath and fpath + os.sep or ''
        for filename in filenames:
            z.write(os.path.join(dirpath, filename), fpath + filename)
    z.close()
    if not os.path.exists(zip_name):  # 判断压缩文件是否存在
        print(src_dir + "压缩文件丢失？？")
        return 1
    z = zipfile.ZipFile(zip_name)
    for names in z.namelist():
        zip_size += z.getinfo(names).file_size  # 获取压缩包内部文件大小
    z.close()
    zip_size2 = getdirsize(src_dir)
    if math.fabs(zip_size - zip_size2) < wc_num and zip_size > 0 and zip_size2 > 0:  # 判断是否压缩成功，根据大小
        print("打包" + get_true_dir(src_dir) + "成功")
    else:
        print("打包" + get_true_dir(src_dir) + "有猫饼")
        return 1
    if code == 1:
        shutil.rmtree(src_dir)
        print(get_true_dir(src_dir) + "文件夹已删除")
    # 删除源文件夹
    return 0



def getdirsize(dir):
    size = 0
    for root, dirs, files in os.walk(winapi_path(dir)):
        size += sum([os.path.getsize(os.path.join(root, name)) for name in files])
    return size


def winapi_path(dos_path, encoding=None):
    if (not isinstance(dos_path, str) and encoding is not None):
        dos_path = dos_path.decode(encoding)
    path = os.path.abspath(dos_path)
    if path.startswith(u"\\\\"):
        return dos_path
    return u"\\\\?\\" + path

def get_true_dir(path):
    if path.startswith(u"\\\\?\\"):
        return path.replace(u"\\\\?\\","")
    else:
        return path

if __name__ == '__main__':
    pass
    dir = r"Z:\1.zip"
    # un_ziprar(dir)
